package main

import (
	"fmt"
	"sort"
	"sync"
	"ys.calc/artifact"
	"ys.calc/role"
	"ys.calc/scenes"
	"ys.calc/weapon"
)

func main() {
	roleTemp := role.InitXiangling().SkillQ()
	weaponArray := weapon.GenerateXianglingWeaponArray()
	suits := artifact.GenerateXianglingSuitArray()

	finalScenes := initDmgScenes(weaponArray, roleTemp, suits)

	sort.Slice(finalScenes, func(i, j int) bool {
		return finalScenes[i].TotalDmg > finalScenes[j].TotalDmg
	})
	for i, scene := range finalScenes {
		if i > 10 {
			break
		}
		r := scene.Role
		fmt.Printf("%v 伤害%v , 套装：%v \t武器：%v \t副词条：%v \n", r.Eon+r.Goblet+r.Circlet, scene.TotalDmg, scene.SuitName, scene.WeaponCode, scene.SubGroupStr)
		//fmt.Printf("%+v 伤害%v , 套装：%v \t武器：%v \t副词条：%v \n", r, scene.TotalDmg, scene.SuitName, scene.WeaponCode, scene.SubGroupStr)
	}
}

func initDmgScenes(weaponArray []weapon.Weapon, roleTemp role.Role, suits []artifact.SuitEffective) []scenes.Scenes {
	var wg sync.WaitGroup
	weaponLen := len(weaponArray)

	weaponChan := generateWeaponChan(weaponArray)
	afterWeapon := equipWeapon(roleTemp, scenes.InitDefault90Enemy(), weaponChan)

	mainStatWords := artifact.PickMainStatWords(roleTemp.AtkUseful, roleTemp.HpUseful, roleTemp.DefenseUseful, roleTemp.MasteryUseful, roleTemp.RechargeUseful)
	mainStatLen := len(mainStatWords)

	subStatWords := artifact.PickSubStat25Words(roleTemp.AtkUseful, roleTemp.HpUseful, roleTemp.DefenseUseful, roleTemp.MasteryUseful, roleTemp.RechargeUseful)
	subStatLen := len(subStatWords)

	delta := weaponLen * mainStatLen * subStatLen * len(suits)

	wg.Add(delta)

	afterMainStatWords := wearMainStat(mainStatWords, afterWeapon)

	afterSubStatWords := wearSubStat(subStatWords, afterMainStatWords)

	finalScenes := wearSuit(suits, afterSubStatWords, &wg)
	wg.Wait()

	return finalScenes
}

func generateWeaponChan(array []weapon.Weapon) <-chan weapon.Weapon {
	out := make(chan weapon.Weapon)
	go func() {
		for _, n := range array {
			out <- n
		}
		close(out)
	}()
	return out
}

func wearSuit(suits []artifact.SuitEffective, afterSubStatWords <-chan scenes.Scenes, wg *sync.WaitGroup) []scenes.Scenes {
	index := 0
	var allRole []scenes.Scenes
	for afterSub := range afterSubStatWords {
		for _, suit := range suits {
			sceneTemp := afterSub
			suit.Suit2(&sceneTemp)
			suit.Suit4(&sceneTemp)
			sceneTemp.WeaponSpFunc(&sceneTemp.Role)
			sceneTemp.Role.RoleSpFunc(&sceneTemp.Role)
			sceneTemp.CalcDmg()
			allRole = append(allRole, sceneTemp)
			index++
			wg.Done()
		}
	}
	return allRole
}

func crutch(sceneTemp *scenes.Scenes) {
	sceneTemp.DoubleFireTeam()
	sceneTemp.InstructorBennett(191 + 620)
	sceneTemp.Vv4Kazuha(965)
}

func wearSubStat(subGroups []artifact.SubStatWord, afterMainStatWords <-chan scenes.Scenes) <-chan scenes.Scenes {
	afterSubStatWords := make(chan scenes.Scenes)
	go func() {
		for roleAfterMain := range afterMainStatWords {

			for _, subGroup := range subGroups {
				var afterSub = roleAfterMain
				for _, statWord := range subGroup.StatWord {
					statWord.BonusFunc(&afterSub.Role)
				}
				afterSub.SubGroupStr = subGroup.SubGroupStr
				afterSubStatWords <- afterSub
			}
		}
		close(afterSubStatWords)
	}()
	return afterSubStatWords
}

func equipWeapon(roleTemp role.Role, enemy scenes.Enemy, weaponChan <-chan weapon.Weapon) <-chan scenes.Scenes {
	afterWeapon := make(chan scenes.Scenes)
	go func() {
		for weaponBase := range weaponChan {
			roleBase := roleTemp
			roleBase.Atk += weaponBase.Atk
			weaponBase.SubStateFunc(&roleBase)
			scenes0 := scenes.Scenes{
				Role:         roleBase,
				WeaponCode:   weaponBase.Name,
				WeaponSpFunc: weaponBase.SpFunc,
				Enemy:        enemy,
			}
			afterWeapon <- scenes0
		}
		close(afterWeapon)
	}()

	return afterWeapon
}

func wearMainStat(mainStatWords []artifact.MainStat, afterWeapon <-chan scenes.Scenes) <-chan scenes.Scenes {
	afterMainStatWords := make(chan scenes.Scenes)
	go func() {
		for roleBase := range afterWeapon {

			for _, mainStat := range mainStatWords {
				var afterMain = roleBase
				for _, mainWord := range mainStat.Main {
					mainWord.BonusFunc(&afterMain.Role)
				}
				afterMainStatWords <- afterMain
			}
		}
		close(afterMainStatWords)
	}()

	return afterMainStatWords
}
